/*
 Class:     Organiser
 Author:    Lusana A
 Desc:      A facade class, that acts as the main controller or mediator
            It facilitates the following:
            1. initialisation where it reads the xml file of rules: init()
            2. run the rules to find paths that match: run_rules()
            3. run file system operations on matched paths: perform_operation()
*/

#ifndef _INCLUDES_
#define _INCLUDES_
    #include <boost/filesystem/operations.hpp>
    #include <QtGui/QApplication>
    #include <sstream>
    #include <iostream>
    #include <fstream>
    #include <string>
    #include <vector>
    #include <list>
    #include <cstdlib>
    #include <map>
#endif

#include "curl/curl.h"
#include "vars.h"
#include "httprequest.h"


using namespace boost;
using namespace std;

namespace bf = boost::filesystem;

#include "debug.h"
#include <algorithm>
#include <boost/regex.hpp>

#include "rule.h"
using namespace Org;
using std::map;

#ifndef ORGANISER_H
#define ORGANISER_H


namespace Org
{

    struct MatchedPath
    {
        Rule rule;
        bf::path path;
        bf::path to_path;
        bool ok_to_run;
    };

    class Organiser
    {
        static Organiser *s_instance;
        typedef HttpRequest::callback http_callback;
        typedef size_t (test_cb)(void*, size_t, size_t, void*);

    private:
        Organiser();


        bool rule_complies(const Rule &, const bf::path &) const;
        void perform_operation(MatchedPath*);        

    public:
        static bf::path incoming_dir;
        static size_t cb_parse_rulegroups_response(void *buffer, size_t size, size_t nmemb, void *userp);

        // call backs
        void* cb_object;
        static void (*cb_ptr_func)();

        vector<Rule> rules;
        vector<RuleGroup> rule_groups;
        vector<MatchedPath> rule_matches;

        template<typename T> bool insert(T val, char* error = 0);
        template<typename T> bool update(T val, char* error = 0);
        template<typename T> bool remove(T val, char* error = 0);

        static void http_get(char* url, size_t (*)(void*, size_t, size_t, void*));
        static void http_get_discogs(char* url, size_t (*)(void*, size_t, size_t, void*));


        bool rule_delete();
        bool rule_edit();
        bool rule_copy();

        void init() const;
        bool run_rules();
        void execute_matches();

        // remote stuff                
        void get_rule_groups(void*);
        void search_rule_groups();
        void upload_rule_group();

        static size_t write_rule_groups(char *buffer, size_t size, size_t nmemb, char *userp);


        static Organiser *instance()
        {
            if (!s_instance)
                s_instance = new Organiser;
            return s_instance;
        }
    };
}

template<typename T> bool Org::Organiser::insert(T val, char* err)
{
    //cout <<  "Organiser::insert TYPE OF IS" << typeid(val).name() << endl;
    return true;
}


#endif
